package com.ming_za.odupdaterserver.core.service.update;

import com.ming_za.odupdaterserver.api.UpdateListener;
import com.ming_za.odupdaterserver.core.config.ConfigManager;
import com.ming_za.odupdaterserver.core.config.type.IntValue;
import com.ming_za.odupdaterserver.core.exception.BusinessException;
import com.ming_za.odupdaterserver.core.exception.ROEnum;
import com.ming_za.odupdaterserver.core.service.update.res.PreUpdate;
import com.ming_za.odupdaterserver.core.service.update.res.UpdateRequest;
import com.ming_za.odupdaterserver.core.utils.Msg;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 更新监听，实现更新监听接口
 * <p>用于处理更新请求，监听各文件生命周期</p>
 * <p>如需调用更新功能请查看{@link com.ming_za.odupdaterserver.api.Updater}</p>
 */
@Component
public class ODUpdaterListener implements UpdateListener {

    private final Map<String, List<UpdateRequest>> updatePool = new HashMap<>();
    private volatile int maxPoolSize;

    public ODUpdaterListener(ConfigManager configManager) {
        IntValue intValue = configManager.getMaxConcurrentDownload();
        maxPoolSize = intValue.getValue();
        intValue.bindListener(integer -> maxPoolSize = integer);
    }

    /**
     * 判断更新最大数量限制，如果已到达单个ip更新最大通道则抛出异常
     * @param preUpdate 更新对象
     * @param ip 请求ip
     */
    @Override
    public void beforeUpdate(PreUpdate preUpdate, String ip) {

        //找不到资源直接返回
        if (!preUpdate.isFind()){
            return;
        }

        List<UpdateRequest> updates;

        if (!updatePool.containsKey(ip)) {
            synchronized (updatePool) {
                if (!updatePool.containsKey(ip)) {
                    updatePool.put(ip, new ArrayList<>());
                }
            }
        }

        updates = updatePool.get(ip);

        if (updates.size() < maxPoolSize) {
            synchronized (updates) {
                if (updates.size() < maxPoolSize){
                    updates.add(preUpdate.getRes());
                    return;
                }
            }
        }

        throw new BusinessException(ROEnum.UPDATE_MAXIMUM_DOWNLOAD);
    }

    private void removeUpdate(String ip,UpdateRequest res){
        List<UpdateRequest> updates;
        synchronized (updatePool) {
            updates = updatePool.get(ip);
        }

        if (updates != null) {
            synchronized (updates) {
                updates.remove(res);
                if (updates.isEmpty()){
                    synchronized (updatePool) {
                        updatePool.remove(ip);
                    }
                }
            }
        }
    }

    @Override
    public void afterUpdate(UpdateRequest res, String ip) {
        removeUpdate(ip, res);
    }

    @Override
    public void error(UpdateRequest res, String ip, Exception exception) {
        Msg.getInstance().warn("[资源下载]传输中断！ip:" + ip + " | 资源id：" + res.getRes().getResid());
        removeUpdate(ip, res);
    }
}
